package test.lucene.pinyin;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import net.sourceforge.pinyin4j.PinyinHelper;
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType;
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat;
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType;
import net.sourceforge.pinyin4j.format.HanyuPinyinVCharType;
import net.sourceforge.pinyin4j.format.exception.BadHanyuPinyinOutputFormatCombination;

public class Pinyin4jUtil
{
  private static final String SEPERATOR = ",";
  private static final boolean UPPER_CASE = false;
  private static final int TONE_TYPE = 0;
  private static final int V_CHAR_TYPE = 0;

  public static String getPinyin(String chinese, boolean upperCase, int toneType, int vCharType, String seperator)
  {
    StringBuffer pinyinName = new StringBuffer();
    char[] nameChar = chinese.toCharArray();
    HanyuPinyinOutputFormat defaultFormat = getOutputFormat(upperCase, toneType, vCharType);
    for (int i = 0; i < nameChar.length; ++i) {
      if (nameChar[i] > '')
        try
        {
          String[] strs = PinyinHelper.toHanyuPinyinStringArray(
            nameChar[i], defaultFormat);
          if (strs != null)
            for (int j = 0; j < strs.length; ++j) {
              pinyinName.append(strs[j]);
              if (j != strs.length - 1)
                pinyinName.append(seperator);
            }
        }
        catch (BadHanyuPinyinOutputFormatCombination e)
        {
          e.printStackTrace();
        }
      else {
        pinyinName.append(nameChar[i]);
      }
      pinyinName.append(" ");
    }
    return parseTheChineseByObject(discountTheChinese(pinyinName.toString(), seperator), seperator);
  }

  public static String getPinyin(String chinese, boolean upperCase, int toneType, int vCharType)
  {
    return getPinyin(chinese, upperCase, toneType, vCharType, ",");
  }

  public static String getPinyin(String chinese, boolean upperCase, int toneType)
  {
    return getPinyin(chinese, upperCase, toneType, 0, ",");
  }

  public static String getPinyin(String chinese, boolean upperCase)
  {
    return getPinyin(chinese, upperCase, 0, 0, ",");
  }

  public static String getPinyin(String chinese, String seperator)
  {
    return getPinyin(chinese, false, 0, 0, seperator);
  }

  public static String getPinyin(String chinese)
  {
    return getPinyin(chinese, false, 0, 0, ",");
  }

  public static String getPinyinShort(String chinese, boolean upperCase, String seperator)
  {
    StringBuffer pinyinName = new StringBuffer();
    char[] nameChar = chinese.toCharArray();
    HanyuPinyinOutputFormat defaultFormat = getOutputFormat(upperCase);
    try {
      for (int i = 0; i < nameChar.length; ++i) {
        if (nameChar[i] > '')
        {
          String[] strs = PinyinHelper.toHanyuPinyinStringArray(
            nameChar[i], defaultFormat);
          if (strs != null)
            for (int j = 0; j < strs.length; ++j)
            {
              pinyinName.append(strs[j].charAt(0));
              if (j != strs.length - 1)
                pinyinName.append(seperator);
            }
        }
        else
        {
          pinyinName.append(nameChar[i]);
        }
        pinyinName.append(" ");
      }
    } catch (BadHanyuPinyinOutputFormatCombination e) {
      e.printStackTrace();
    }
    return parseTheChineseByObject(discountTheChinese(pinyinName.toString(), seperator), seperator);
  }

  public static String getPinyinShort(String chinese, boolean upperCase)
  {
    return getPinyinShort(chinese, upperCase, ",");
  }

  public static String getPinyinShort(String chinese)
  {
    return getPinyinShort(chinese, false, ",");
  }

  public static Collection<String> getPinyinCollection(String chinese, boolean upperCase, int toneType, int vCharType)
  {
    List<String[]> pinyinList = new ArrayList();
    HanyuPinyinOutputFormat defaultFormat = getOutputFormat(upperCase, toneType, vCharType);
    try {
      for (int i = 0; i < chinese.length(); ++i) {
        String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(
          chinese.charAt(i), defaultFormat);
        if ((pinyinArray != null) && (pinyinArray.length > 0))
          pinyinList.add(pinyinArray);
      }
    }
    catch (BadHanyuPinyinOutputFormatCombination e) {
      e.printStackTrace();
    }

    Set pinyins = null;
    for (String[] array : pinyinList) {
      if ((pinyins == null) || (pinyins.isEmpty())) {
        pinyins = new HashSet();
        for (String charPinpin : array)
          pinyins.add(charPinpin);
      }
      else {
        Set<String> pres = pinyins;
        pinyins = new HashSet();
        for (String pre : pres) {
          for (String charPinyin : array) {
            pinyins.add(pre + charPinyin);
          }
        }
      }
    }
    return pinyins;
  }

  public static Collection<String> getPinyinCollection(String chinese, boolean upperCase, int toneType)
  {
    return getPinyinCollection(chinese, upperCase, toneType, 0);
  }

  public static Collection<String> getPinyinCollection(String chinese, boolean upperCase) {
    return getPinyinCollection(chinese, upperCase, 0, 0);
  }

  public static Collection<String> getPinyinCollection(String chinese) {
    return getPinyinCollection(chinese, false, 0, 0);
  }

  public static Collection<String> getPinyinShortCollection(String chinese, boolean upperCase, int toneType, int vCharType)
  {
    List<String[]> pinyinList = new ArrayList();
    HanyuPinyinOutputFormat defaultFormat = getOutputFormat(upperCase, toneType, vCharType);
    try {
      for (int i = 0; i < chinese.length(); ++i) {
        String[] pinyinArray = PinyinHelper.toHanyuPinyinStringArray(
          chinese.charAt(i), defaultFormat);
        if ((pinyinArray != null) && (pinyinArray.length > 0))
          pinyinList.add(pinyinArray);
      }
    }
    catch (BadHanyuPinyinOutputFormatCombination e) {
      e.printStackTrace();
    }
    Set sorts = new HashSet();
    Set pinyins = null;
    for (String[] array : pinyinList) {
      if ((pinyins == null) || (pinyins.isEmpty())) {
        pinyins = new HashSet();
        for (String charPinpin : array) {
          pinyins.add(charPinpin.substring(0, 1));
          sorts.add(charPinpin.substring(0, 1));
        }
      } else {
        Set<String> pres = pinyins;
        pinyins = new HashSet();
        for (String pre : pres) {
          for (String charPinyin : array) {
            pinyins.add(pre + charPinyin.substring(0, 1));
            sorts.add(pre + charPinyin.substring(0, 1));
          }
        }
      }
    }
    return sorts;
  }

  public static Collection<String> getPinyinShortCollection(String chinese, boolean upperCase, int toneType)
  {
    return getPinyinShortCollection(chinese, upperCase, toneType, 0);
  }

  public static Collection<String> getPinyinShortCollection(String chinese, boolean upperCase) {
    return getPinyinShortCollection(chinese, upperCase, 0, 0);
  }

  public static Collection<String> getPinyinShortCollection(String chinese) {
    return getPinyinShortCollection(chinese, false, 0, 0);
  }

  public static HanyuPinyinOutputFormat getOutputFormat()
  {
    HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
    format.setCaseType(HanyuPinyinCaseType.LOWERCASE);
    format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
    format.setVCharType(HanyuPinyinVCharType.WITH_V);
    return format;
  }

  public static HanyuPinyinOutputFormat getOutputFormat(boolean upperCase) {
    HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
    format.setCaseType((upperCase) ? HanyuPinyinCaseType.UPPERCASE : 
      HanyuPinyinCaseType.LOWERCASE);
    format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
    format.setVCharType(HanyuPinyinVCharType.WITH_V);
    return format;
  }

  public static HanyuPinyinOutputFormat getOutputFormat(boolean upperCase, int toneType, int vCharType)
  {
    HanyuPinyinOutputFormat format = new HanyuPinyinOutputFormat();
    format.setCaseType((upperCase) ? HanyuPinyinCaseType.UPPERCASE : 
      HanyuPinyinCaseType.LOWERCASE);
    if (toneType == 0)
      format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
    else if (toneType == 1)
      format.setToneType(HanyuPinyinToneType.WITH_TONE_MARK);
    else if (toneType == 2)
      format.setToneType(HanyuPinyinToneType.WITH_TONE_NUMBER);
    else {
      format.setToneType(HanyuPinyinToneType.WITHOUT_TONE);
    }

    if (vCharType == 0)
      format.setVCharType(HanyuPinyinVCharType.WITH_V);
    else if (vCharType == 1)
      format.setVCharType(HanyuPinyinVCharType.WITH_U_UNICODE);
    else if (vCharType == 2)
      format.setVCharType(HanyuPinyinVCharType.WITH_U_AND_COLON);
    else {
      format.setVCharType(HanyuPinyinVCharType.WITH_V);
    }
    return format;
  }

  public static boolean isNumeric(String str)
  {
    if ((str == null) || (str.length() == 0)) {
      return false;
    }
    for (int i = str.length(); --i >= 0; ) {
      if (!Character.isDigit(str.charAt(i))) {
        return false;
      }
    }
    return true;
  }

  public static boolean isLetter(String str)
  {
    if ((str == null) || (str.length() == 0)) {
      return false;
    }
    for (int i = str.length(); --i >= 0; ) {
      if (!Character.isAlphabetic(str.charAt(i))) {
        return false;
      }
    }
    return true;
  }

  private static List<Map<String, Integer>> discountTheChinese(String theStr, String seperator)
  {
    List mapList = new ArrayList();

    Map onlyOne = null;
    String[] firsts = theStr.split(" ");

    for (String str : firsts) {
      onlyOne = new Hashtable();
      String[] china = str.split(seperator);

      for (String s : china) {
        Integer count = (Integer)onlyOne.get(s);
        if (count == null) {
          onlyOne.put(s, new Integer(1));
        } else {
          onlyOne.remove(s);
          count = Integer.valueOf(count.intValue() + 1);
          onlyOne.put(s, count);
        }
      }
      mapList.add(onlyOne);
    }
    return mapList;
  }

  private static String parseTheChineseByObject(List<Map<String, Integer>> list, String seperator)
  {
    Map<String, ?> first = null;
    for (int i = 0; i < list.size(); ++i)
    {
      Map temp = new Hashtable();

      if (first != null)
      {
        for (String s : first.keySet()) {
          for (String s1 : ((Map<String, Integer>)list.get(i)).keySet()) {
            String str = s + s1;
            temp.put(str, Integer.valueOf(1));
          }
        }

        if ((temp != null) && (temp.size() > 0))
          first.clear();
      }
      else {
        for (Iterator iter = ((Map<String, Integer>)list.get(i)).keySet().iterator(); iter.hasNext(); ) { String s = (String)iter.next();
          String str = s;
          temp.put(str, Integer.valueOf(1)); }

      }

      if ((temp != null) && (temp.size() > 0)) {
        first = temp;
      }
    }
    String returnStr = "";
    if (first != null)
    {
      for (String str : first.keySet()) {
        returnStr = returnStr + str + seperator;
      }
    }
    if (returnStr.length() > 0) {
      returnStr = returnStr.substring(0, returnStr.length() - 1);
    }
    return returnStr;
  }

  public static void main(String[] args) {
    String s = "重庆";
    String pinyin = getPinyin(s, ",");
    System.out.println(pinyin);
    String jianpin = getPinyinShort(s, true, ",");
    System.out.println(jianpin);

    Collection<String> collection = getPinyinCollection(s);
    for (String str : collection)
      System.out.println(str);
  }
}